<script>
import util from "../../libs/util";
import KtTableColumnOfTypeIsText
  from "/src/components/node-kantboot/components/KtTable/InColumnComponents/KtTableColumnOfTypeIsText.vue";
import KtTableColumnOfTypeIsNumber
  from "/src/components/node-kantboot/components/KtTable/InColumnComponents/KtTableColumnOfTypeIsNumber.vue";
import KtTableColumnOfTypeIsImg
  from "/src/components/node-kantboot/components/KtTable/InColumnComponents/KtTableColumnOfTypeIsImg.vue";
import KtTableColumnOfTypeIsEnum
  from "/src/components/node-kantboot/components/KtTable/InColumnComponents/KtTableColumnOfTypeIsEnum.vue";
import KtTableColumnOfTypeIsDatetime
  from "/src/components/node-kantboot/components/KtTable/InColumnComponents/KtTableColumnOfTypeIsDatetime.vue";
import KtTableSearchOfTypeIsText
  from "/src/components/node-kantboot/components/KtTable/InSearchComponents/KtTableSearchOfTypeIsText.vue";
import KtTableSearchOfTypeIsNumber
  from "/src/components/node-kantboot/components/KtTable/InSearchComponents/KtTableSearchOfTypeIsNumber.vue";
import KtTableSearchOfTypeIsDatetime
  from "/src/components/node-kantboot/components/KtTable/InSearchComponents/KtTableSearchOfTypeIsDatetime.vue";
import KtTableDialogOfSave from "/src/components/node-kantboot/components/KtTable/KtTableDialogOfSave.vue";
import SearchInKtTable from "/src/components/node-kantboot/components/KtTable/InTableComponents/SearchInKtTable.vue";
import KtIcon from "/src/components/node-kantboot/components/KtIcon/KtIcon.vue";

export default {
  components: {
    KtIcon,
    SearchInKtTable,
    KtTableSearchOfTypeIsDatetime,
    KtTableSearchOfTypeIsNumber,
    KtTableSearchOfTypeIsText,
    KtTableColumnOfTypeIsDatetime,
    KtTableColumnOfTypeIsEnum,
    KtTableColumnOfTypeIsImg, KtTableColumnOfTypeIsNumber, KtTableColumnOfTypeIsText,
    KtTableDialogOfSave
  },
  props: {
    columns: {
      type: Array,
      default: []
    },
    height: {
      type: String,
      default: "100vh"
    },
    requestUri: {
      type: String,
      default: ''
    },
    isHasChildren: {
      type: Boolean,
      default: false
    },
    isHasEdit: {
      type: Boolean,
      default: true
    },
    isHasRemove: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      // 是否有选择，如果有选择，也会显示确定选择按钮
      isHasSelect: false,

      // id对应的字段
      idField: 'id',
      // 处在编辑状态的id
      editId: '',
      pageSizes: [10, 20, 30, 40, 50],
      requestParam: {
        data: {
          and: [],
          or: []
        },
        pageNumber: 1,
        pageSize: 10
      },
      bodyData: {
        content: [],
        number: 1,
        size: 10,
        totalElements: 1,
        totalPage: 1
      },
      isLoading: false,
      headerHeight: 0,
      uuid: util.generateUUID(32),
      isUpSearch: false,
      // 选项
      selection: [],

      // 保存对话框,这里是为了调用保存对话框的方法
      isSaveIf: true,

      requestParamOfEdit: {
        id: '',
      }
    }
  },
  mounted() {
    // 获取所有isSearch为true的字段
    let searchFields = this.columns.filter(column => column.isSearch);
    // 遍历所有的字段
    searchFields.forEach(column => {
      if (!column.searchSetting) {
        column.searchSetting = {}
      }
      if (!column.searchSetting.operatorCode) {
        column.searchSetting.operatorCode = this.getOperatorCode(column);
      }
    });

    this.getHeaderHeight();
    this.initSort(this.columns);
    this.getBodyData();

  },
  methods: {
    /**
     * 根据id取消选择
     */
    cancelSelection(id) {
      for (let i = 0; i < this.selection.length; i++) {
        if (this.selection[i][this.idField] === id) {
          this.selection.splice(i, 1);
          return;
        }
      }
    },

    /**
     * 根据id删除
     * @param id
     */
    removeById(id) {
      // 是否确认删除
      this.$confirm('是否确认删除？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.removeByIdRequest(id);
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    /**
     * 批量删除
     */
    removeBatch() {
      if (this.selection.length === 0) {
        this.$message.warning("请选择要删除的数据");
        return;
      }
      // 是否确认删除
      this.$confirm('是否确认删除？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        // 总数
        let total = this.selection.length;
        // 失败的数量
        let fail = 0;
        // 成功的数量
        let success = 0;
        // 剩余
        let surplus = 0;
        let loading = this.$loading({
          lock: true,
          text: `正在删除数据，成功${success}条，失败${fail}条，剩余${surplus}条`,
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)',
        });
        let selection = JSON.parse(JSON.stringify(this.selection));

        for (let i = 0; i < selection.length; i++) {

          await new Promise((resolve, reject) => {
            let data = {};
            data[this.idField] = selection[i][this.idField];
            this.$kt.requestSecurity.send({
              uri: `${this.requestUri}/remove`,
              method: 'POST',
              data,
              stateSuccess: (res) => {
                success++;
                this.cancelSelection(selection[i][this.idField]);
                setTimeout(() => {
                  resolve("");
                }, 100);
              },
              stateFail: (res) => {
                fail++;
                this.$message.error(res.errMsg);
                setTimeout(() => {
                  reject("");
                }, 100);

              }
            });
          });

          surplus = total - success - fail;
          loading.close();
          loading = this.$loading({
            lock: true,
            text: `正在删除数据，总共${total}条数据，成功${success}条，失败${fail}条，剩余${surplus}条`,
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
        }
        setTimeout(() => {
          loading.close();
          this.getBodyData();
        }, 1000);
        this.getBodyData();

      });
    },

    removeByIdRequest(id) {
      let data = {};
      data[this.idField] = id;
      this.$kt.requestSecurity.send({
        uri: `${this.requestUri}/remove`,
        method: 'POST',
        data,
        stateSuccess: (res) => {
          this.$message.success(res.msg);
          this.cancelSelection(id);
          this.getBodyData();
        },
        stateFail: (res) => {
          this.$message.error(res.errMsg);
        }
      });
    },

    editInChange(column, value) {
      this.requestParamOfEdit[column.field] = value;
      console.log(JSON.stringify(this.requestParamOfEdit), "----");
    },
    getSaveRequestUrl() {
      return this.requestUri + "/save";
    },
    requestOfSave() {
      // element-plus中的loading

      let requestParamOfEdit = JSON.parse(JSON.stringify(this.requestParamOfEdit));
      requestParamOfEdit[this.idField] = this.editId;

      this.$kt.requestSecurity.send({
        uri: this.getSaveRequestUrl(),
        method: 'POST',
        data: requestParamOfEdit,
        stateSuccess: (res) => {
          let bodyDataContent = this.bodyData.content;
          for (let i = 0; i < bodyDataContent.length; i++) {
            if (bodyDataContent[i][this.idField] === this.editId) {
              bodyDataContent[i] = res.data;
              break;
            }
          }
          this.bodyData.content = bodyDataContent;
          this.$message.success(res.msg);
          this.getBodyData();
          this.close();
          this.$emit('saveSuccess', this.form);
        },
        stateFail: (res) => {
          this.closeLoading();
          this.$message.error(res.errMsg);

        }
      });
    },
    /**
     * 初始化sort
     */
    initSort(columns) {
      columns.forEach(column => {
        if (column.isSort) {
          this.requestParam.sort = column.field;
          this.requestParam.orderBy = column.orderBy ? column.orderBy : 'asc';
          return false;
        }
      });
      // 获取所有含有isNotNull的字段
      let isNotNullFields = columns.forEach(column => {
        if (column.isNotNull) {
          if(!this.requestParam.data){
            this.requestParam.data = {};
          }
          if(!this.requestParam.data.isNotNull){
            this.requestParam.data.isNotNull = [];
          }
          this.requestParam.data.isNotNull.push(column.field);
        }
        if(column.isNull){
          if(!this.requestParam.data){
            this.requestParam.data = {};
          }
          if(!this.requestParam.data.isNull){
            this.requestParam.data.isNull = [];
          }
          this.requestParam.data.isNull.push(column.field);
        }
      });
    },

    /**
     * 获取没有无用参数的requestParam
     */
    getRequestParam() {
      let requestParam = JSON.parse(JSON.stringify(this.requestParam));
      // 比如有一个字段是空的，就删除这个字段
      requestParam.data.and = requestParam.data.and.filter(item => item.value !== '' && item.value !== null && item.value !== undefined && item.value !== []);
      return requestParam;
    },
    /**
     * 为了更好的封装调用而定义的
     */
    ktEmit(emitName, ...emitArgs) {
      this.$emit(emitName, ...emitArgs);
      this.$emit("ktEmit", {
        emitName,
        emitArgs
      })
    },
    setIsHasSelect(val) {
      this.isHasSelect = val;
    },
    /**
     * 确定选择
     */
    select() {
      // this.$emit('select', this.selection)
      this.ktEmit('select', this.selection);
    },
    /**
     * 判断是否在选项之中
     */
    isSelectionHasRowKey(row) {
      // 判断是否在选项之中
      return this.selection.some(item => item[this.idField] === row[this.idField]);
    },
    selectionSelect(row) {
      if (this.isSelectionHasRowKey(row)) {
        this.selection = this.selection.filter(item => item[this.idField] !== row[this.idField]);
      } else {
        this.selection.push(row);
      }
    },
    /**
     * 全选此页
     */
    selectionSelectPageAll() {
      let content = this.bodyData.content;
      for (let i = 0; i < content.length; i++) {
        if (!this.isSelectionHasRowKey(content[i])) {
          this.selection.push(content[i]);
        }
      }
    },
    /**
     * 清除此页选项
     */
    selectionClearPage() {
      let content = this.bodyData.content;
      for (let i = 0; i < content.length; i++) {
        if (this.isSelectionHasRowKey(content[i])) {
          this.selection = this.selection.filter(item => item[this.idField] !== content[i][this.idField]);
        }
      }
    },
    /**
     * 清除所有选项
     */
    selectionClearAll() {
      this.selection = [];
    },

    /**
     * 获取header的高度
     */
    getHeaderHeight() {
      let header = document.getElementById(`header_${this.uuid}`);
      if (header) {
        this.headerHeight = header.clientHeight;
      }
    },
    loading() {
      this.isLoading = true;
    },
    closeLoading() {
      this.isLoading = false;
    },
    getBodyDataRequestUrl() {
      return `${this.requestUri}/getBodyData`;
    },
    getBodyData() {
      this.initSort(this.columns);
      this.loading();
      this.$kt.request.send({
        uri: this.getBodyDataRequestUrl(),
        method: 'POST',
        data: this.getRequestParam(),
        stateSuccess: (res) => {
          this.bodyData = res.data;
          this.bodyData = this.handleBodyData(this.bodyData);
          this.closeLoading();
        },
        stateFail: (res) => {
          this.$message.error(res.errMsg);
        }
      });
    },
    handleBodyData(bodyData) {
      return bodyData;
    },
    changePageSize(val) {
      this.requestParam.pageSize = val;
      this.getBodyData();
    },
    changePageNumber(val) {
      this.requestParam.pageNumber = val;
      this.getBodyData();
    },
    /**
     * 判断是否处于编辑状态
     */
    isEditStatus(row) {
      return row[this.idField] === this.editId;
    },
    /**
     * 进入编辑状态
     */
    toEdit(row) {
      this.editId = row[this.idField];
    },
    /**
     * 获取行状态
     */
    getRowStatus(row) {
      if (this.isEditStatus(row)) {
        return 'edit'
      }
      return 'view'
    },
    /**
     * 确认编辑
     */
    confirmEdit(item) {
      this.requestOfSave();
      this.editId = ''

    },
    /**
     * 处理编辑
     */
    handleEdit(item) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("操作成功")
        }, 1000)
      });
    },
    /**
     * 取消编辑
     */
    cancelEdit() {
      this.editId = ''
    },
    /**
     * 返回操作状态编码
     */
    getOperationStatus(row) {
      if (this.isEditStatus(row)) {
        return 'edit'
      }
      return 'view'
    },
    /**
     * 根据column获取默认的operatorCode
     */
    getOperatorCode(column) {
      if (column.searchSetting && column.searchSetting.operatorCode) {
        return column.searchSetting.operatorCode
      }

      if (column.type === 'text' || column.type === 'textarea') {
        return 'vague'
      } else if (column.type === 'number') {
        return 'eq'
      } else if (column.type === 'enum') {
        return 'eq'
      } else if (column.type === 'datetime') {
        return 'closeInterval'
      }
    },

    /**
     * 搜索值改变
     */
    searchValueChange(column, value) {
      // 获取到字段的值，和requestParam中的data是否有相同的字段
      let index = this.requestParam.data.and.findIndex(item => item.field === column.field);
      let operatorCode = column.searchSetting.operatorCode;
      let valueNew = value;
      // 如果有相同的字段
      if (index !== -1) {
        // 更新值
        this.requestParam.data.and[index].value = valueNew
      } else {
        // 如果没有相同的字段，就添加一个新的字段
        this.requestParam.data.and.push({
          operatorCode: operatorCode,
          field: column.field,
          value: valueNew
        });
      }
    },
    fieldEval(row, field) {
      try {
        return eval(`row.${field}`);
      } catch (e) {
        return ''
      }
    },
    saveSuccess() {
      this.getBodyData();
      this.isSaveIf = false;
      setTimeout(() => {
        this.isSaveIf = true;
      }, 100);
    }
  },
  watch: {
    // 监听isUpSearch的变化
    isUpSearch(val) {
      this.$nextTick(() => {
        this.getHeaderHeight();
      })
    },
    // 监听editId的变化
    editId(val) {
      this.requestParamOfEdit = {};
    }
  }
}
</script>

<template>
  <kt-table-dialog-of-save
      v-if="isSaveIf"
      :columns="columns"
      :request-uri="requestUri"
      ref="dialogOfSave"
      @saveSuccess="saveSuccess"
  ></kt-table-dialog-of-save>

  <el-card>
    <template #header>
      <div :id="`header_${uuid}`">
        <div v-if="!isUpSearch">
          <search-in-kt-table
              :columns="columns"
              @searchValueChange="searchValueChange"
              @getBodyData="getBodyData"
          ></search-in-kt-table>
        </div>

        <!--     收起     -->
        <div class="up-search-box">
          <div style="height: 5px"></div>
          <a-button
              type="dashed"
              @click="isUpSearch = !isUpSearch">
            <kt-icon :icon="isUpSearch ? 'el-icon-arrow-down' : 'el-icon-arrow-up'"></kt-icon>
            <span style="margin-left: 10px">{{ isUpSearch ? $i18n.enToGlobal('open') : $i18n.enToGlobal('close') }}</span>
          </a-button>
          <div style="height: 5px"></div>
        </div>

        <div>
          <a-button @click="getBodyData()">
            <kt-icon icon="el-icon-refresh"></kt-icon>
          </a-button>
          <div style="display: inline-block;float: right">
            <a-button
                type="primary"
                @click="()=>$refs.dialogOfSave.open()">
              <kt-icon icon="ant-icon-plus-outlined"></kt-icon>
            </a-button>
            <a-button
                :disabled="selection.length===0"
                @click="removeBatch"
                style="margin-left: 10px"
                type="primary" danger>
              <kt-icon icon="ant-icon-delete-outlined"></kt-icon>
            </a-button>
            <a-button style="margin-left: 10px"
                      :disabled="selection.length===0"
                      @click="select" v-if="isHasSelect">
              确定选择
            </a-button>

            <div style="margin-left: 10px;display: inline-block">
              <slot name="headerBox" :selection="selection"></slot>
            </div>
          </div>


        </div>
      </div>
    </template>


    <el-table
        v-loading="isLoading"
        style="border-radius: 20px"
        :data="bodyData.content"
        :cell-style="{textAlign: 'center'}"
        :row-style="{textAlign: 'center'}"
        :header-cell-style="{textAlign: 'center'}"
        border
        row-key="id"
        :lazy="false"
        :height="`calc(${height} - 130px - ${headerHeight}px)`"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
    >


      <el-table-column v-if="isHasChildren"
      ></el-table-column>


      <el-table-column width="60px">
        <template #header="{column}">
          <div class="check-box">
            <el-dropdown>
              <el-button>
                <kt-icon
                    size="10px"
                    icon="el-icon-arrow-down"></kt-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item
                      @click="selectionSelectPageAll()">全选此页
                  </el-dropdown-item>

                  <el-dropdown-item
                      @click="selectionClearPage()">清除此页
                  </el-dropdown-item>

                  <el-dropdown-item
                      @click="selectionClearAll()">清除所有
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </template>
        <template #default="{row,$index}">
          <div class="check-box"
               @click="selectionSelect(row)">
            <div class="check-div">
              <div
                  v-if="isSelectionHasRowKey(row)"
                  class="check-div-dot"></div>
            </div>
          </div>

        </template>
      </el-table-column>

      <!-- 序号 -->
      <el-table-column label="" width="60">
        <template #default=" {row,$index,a} ">
<!--          <span>{{ // JSON.stringify(row) }}</span>-->
          <span v-if="!row.parentId">{{ $index + 1 }}</span>
          <span v-else style="font-weight: bold">{{"~~"}}</span>
        </template>

      </el-table-column>

      <template v-for="column in columns">
        <el-table-column
            v-if="!column?.isHide"
            :label="$i18n.zhToGlobal(column.label)"
            :prop="column.field"
            :width="column.width">
          <template #default="{row}">
            <!-- 根据不同的类型，渲染不同的组件 -->

            <!-- 文本类型 -->
            <kt-table-column-of-type-is-text
                v-if="column.type === 'text'"
                :column="column"
                :value="fieldEval(row,column.field)"
                :row-status="getRowStatus(row)"
                @change="editInChange(column,$event)"
            ></kt-table-column-of-type-is-text>

            <!-- textaera类型 -->
            <pre v-if="column.type === 'textarea'">{{ fieldEval(row, column.field) }}</pre>


            <!-- 数字类型 -->
            <kt-table-column-of-type-is-number
                v-if="column.type === 'number'"
                :column="column"
                :value="fieldEval(row,column.field)"
                :row-status="getRowStatus(row)"
                @change="editInChange(column,$event)"
            ></kt-table-column-of-type-is-number>

            <!-- 图片类型 -->
            <kt-table-column-of-type-is-img
                v-if="column.type === 'img'"
                :column="column"
                :value="fieldEval(row,column.field)"
                :row-status="getRowStatus(row)"
                @change="editInChange(column,$event)"
            ></kt-table-column-of-type-is-img>

            <!-- 枚举类型 -->
            <kt-table-column-of-type-is-enum
                v-if="column.type === 'enum'"
                :column="column"
                :value="fieldEval(row,column.field)"
                :row-status="getRowStatus(row)"
                @change="editInChange(column,$event)"
            ></kt-table-column-of-type-is-enum>

            <!-- 时间类型 -->
            <kt-table-column-of-type-is-datetime
                v-if="column.type === 'datetime'"
                :column="column"
                :value="fieldEval(row,column.field)"
                :row-status="getRowStatus(row)"
                @change="editInChange(column,$event)"
            ></kt-table-column-of-type-is-datetime>

            <!--       自定义     -->
            <template v-if="column.type==='custom'">
              <slot :name="column.field" :row="row"></slot>
            </template>

          </template>
        </el-table-column>


      </template>

      <el-table-column width="100">
      </el-table-column>
      <!--   右侧，操作  -->
      <el-table-column :label="$i18n.enToGlobal('operate')" width="180"
                       fixed="right">
        <template #default="{row}">
          <div v-if="getOperationStatus(row) ==='view'"
               style="margin-bottom: 10px">
            <!--     插槽     -->
            <slot name="operationPrepend" :row="row"></slot>
          </div>

          <template v-if="getOperationStatus(row) ==='view'">
            <!-- 编辑 -->
            <el-button
                v-if="isHasEdit"
                @click="toEdit(row)"
                type="primary" size="mini">
              <kt-icon icon="el-icon-edit"></kt-icon>
            </el-button>
            <!-- 删除 -->
            <el-button type="danger"
                       v-if="isHasRemove"
                       @click="removeById(row[idField])"
                       size="mini">
              <kt-icon
                  color="#fff"
                  icon="el-icon-delete"></kt-icon>
            </el-button>
          </template>
          <template v-else>
            <el-button
                @click="confirmEdit"
                type="primary" size="mini">
              <kt-icon icon="el-icon-check"></kt-icon>
            </el-button>
            <el-button
                @click="cancelEdit"
                type="info" size="mini">
              <kt-icon
                  color="#fff"
                  icon="el-icon-close"></kt-icon>
            </el-button>
          </template>
          <div v-if="getOperationStatus(row) ==='view'"
               style="margin-top: 10px">
            <!--     插槽     -->
            <slot name="operationAppend" :row="row"></slot>
          </div>
        </template>
      </el-table-column>

    </el-table>

    <div class="footer">
      <el-pagination
          class="pagination"
          layout="total, sizes, prev, pager, next, jumper"
          :page-sizes="pageSizes"
          :total="bodyData.totalElements"
          :page-size="requestParam.pageSize"
          :current-page="requestParam.pageNumber"
          @size-change="changePageSize"
          @current-change="changePageNumber"
      ></el-pagination>
    </div>

  </el-card>

</template>

<style lang="scss" scoped>
.row {
  text-align: center;
}

.footer {
  position: relative;
  height: 30px;
  margin-top: 20px;

  .pagination {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}

.up-search-box {
  text-align: center;
}

.check-box {
  position: relative;
  width: 100%;
  cursor: pointer;
}

.check-div {
  position: relative;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-block;
  border: 1px solid #000000;
}

.check-div-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background-color: #000000;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.el-table {
  width: 100%;

  .el-table__header-wrapper table,
  .el-table__body-wrapper table {
    width: 100% !important;
  }

  .el-table__body,
  .el-table__footer,
  .el-table__header {
    table-layout: auto;
  }
}

</style>